package cool.taomu.toolkit.apilog

import com.google.common.eventbus.AsyncEventBus
import com.google.inject.Inject
import cool.taomu.toolkit.apilog.entity.ApiCallEventEntity
import java.lang.annotation.Annotation
import java.lang.reflect.Method
import java.time.LocalDateTime
import javax.ws.rs.DELETE
import javax.ws.rs.GET
import javax.ws.rs.HEAD
import javax.ws.rs.OPTIONS
import javax.ws.rs.POST
import javax.ws.rs.PUT
import javax.ws.rs.Path
import org.aopalliance.intercept.MethodInterceptor
import org.aopalliance.intercept.MethodInvocation

class ApiLogInterceptor implements MethodInterceptor {

    @Inject(optional=true)
    AsyncEventBus eventbus;

    override invoke(MethodInvocation invocation) throws Throwable {
        var Method method = invocation.getMethod();

        var String httpMethod = getHttpMethod(method);
        if (httpMethod === null || !method.isAnnotationPresent(Path) || eventbus === null) {
            return invocation.proceed();
        }

        var Path methodPath = method.getAnnotation(Path);
        var String methodPathValue = methodPath.value();

        var Class<?> targetClass = method.getDeclaringClass();
        var Path classPath = targetClass.getAnnotation(Path);
        var String classPathValue = (classPath !== null) ? classPath.value() : "";

        var String fullPath = normalizePath(classPathValue + methodPathValue);

        // 发布事件
        var event = new ApiCallEventEntity(
            method.getName(),
            httpMethod,
            fullPath,
            LocalDateTime.now()
        );
        eventbus.post(event);

        return invocation.proceed();
    }

    private def String getHttpMethod(Method method) {
        for (Class<? extends Annotation> annotation : #[
            GET,
            POST,
            PUT,
            DELETE,
            HEAD,
            OPTIONS
        ]) {
            if (method.isAnnotationPresent(annotation)) {
                return annotation.getSimpleName().toUpperCase();
            }
        }
        return null;
    }

    private def String normalizePath(String path) {
        if(path === null || path.isEmpty()) return "/";
        return path.replaceAll("/{2,}", "/");
    }
}
